﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Forms;



namespace TransformBLG
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private string _finalFile = string.Empty;
        private ApplicationStep _currentAppFlow;
        private ProcessFiles _processFiles;
        private bool _lookForRelog = true;
        private string _relogFileDIR;
        private string _relogFileName = "tempRelogMerge.csv";



        /// <summary>
        /// Initializes a new instance of the <see cref="MainWindow"/> class.
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();


            this._processFiles = new ProcessFiles();


            lpLoading.OnNoClick += lpLoading_OnNoClick;
            lpLoading.OnOKClick +=lpLoading_OnOKClick;
            lpLoading.OnYesClick += lpLoading_OnYesClick;

            
            this._processFiles.OnRelogComplete +=_processFiles_OnRelogComplete;
            
            //set the initial processing step
            this._currentAppFlow = ApplicationStep.CheckForFile;
        }

       

       
        private enum ApplicationStep
        {
            CheckForFile,
            ExecuteRelog,
            ProcessRelogResults

        }

        /// <summary>
        /// Determines the application flow.
        /// </summary>
        private void DetermineApplicationFlow()
        {
            try
            {
                switch (this._currentAppFlow)
                {
                    case ApplicationStep.CheckForFile:
                        {
                            if (_relogFileDIR == default(string) || !_relogFileDIR.Contains(txtWorkingDir.Text))
                            {
                                this._relogFileDIR = string.Format(@"{0}\{1}", txtWorkingDir.Text, this._relogFileName);
                                this._finalFile = string.Format(@"{1}\{0}.csv", txtOutputName.Text, txtWorkingDir.Text);
                            }

                            if (!this._finalFile.Contains(txtOutputName.Text))
                            {
                                this._finalFile = string.Format(@"{1}\{0}.csv", txtOutputName.Text, txtWorkingDir.Text);
                            }

                            if (!CheckForExistingFile())
                            {
                                this._currentAppFlow = ApplicationStep.ExecuteRelog;
                                DetermineApplicationFlow();
                            }

                            break;
                        }
                    case ApplicationStep.ExecuteRelog:
                        {
                            DisplayMessageFromBGThread("Executing relog for BLG files.", LoadingPanelDisplayType.LoadingScreen);
                            StringBuilder files = new StringBuilder();
                            listBox1.Items.Cast<string>().ToList().Where(item => item.Contains(".blg")).ToList().ForEach(item => files.AppendFormat(@"""{0}"" ", item));
                            if (files.Length != 0)
                            {
                                this._lookForRelog = true;
                                this._processFiles.ExecuteRelog(files.ToString(), this._relogFileDIR);
                            }
                            else
                            {
                                //looks like we had no Blg go straight to CSV processing
                                //we need to throw this on a BG thread for UI.
                                
                                System.Threading.Thread workerThread = new System.Threading.Thread(DetermineApplicationFlow);
                                this._lookForRelog = false;
                                this._currentAppFlow = ApplicationStep.ProcessRelogResults;
                                workerThread.Start();
                            }
                            break;
                        }
                    case ApplicationStep.ProcessRelogResults:
                        {
                            object _lockObj = new object();

                            DisplayMessageFromBGThread("Reformatting relog files.", LoadingPanelDisplayType.LoadingScreen);

                            List<string> filesToProcess = listBox1.Items.Cast<string>().ToList().Where(item => item.Contains(".csv")).ToList();
                            if(this._lookForRelog)
                                filesToProcess.Add(this._relogFileDIR);

                          
                            filesToProcess.ForEach(item => this._processFiles.ReadWriteCSV(item, this._finalFile));
                         
  
                            DisplayMessageFromBGThread("Done processing files(s).", LoadingPanelDisplayType.OK);

                            this.Dispatcher.Invoke((Action)(() =>
                            {
                                System.Diagnostics.Process.Start("explorer.exe", string.Format(@"{0}", txtWorkingDir.Text));
                            }));
                            break;
                        }
                }
            }
            catch(Exception ex)
            {
                DisplayMessageFromBGThread(string.Format("ERROR: {0}", ex.Message), LoadingPanelDisplayType.OK);
            }

           
        }


        /// <summary>
        /// Checks for existing file.
        /// </summary>
        /// <returns></returns>
        private bool CheckForExistingFile()
        {
            bool didFindFile = false;
            if (System.IO.File.Exists(this._finalFile))
            {
                DisplayMessageFromBGThread(string.Format("A file with the same name already exisits at: \n\r{0} \n\rClick 'Yes' to keep (re-name) the file or 'No' to delete the file.", this._finalFile),
                    LoadingPanelDisplayType.YesNo);
                
                didFindFile = true;
            }

            return didFindFile;
        }

        /// <summary>
        /// Displays the message from bg thread.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="displayType">The display type.</param>
        private void DisplayMessageFromBGThread(string message, LoadingPanelDisplayType displayType)
        {
            this.Dispatcher.Invoke((Action)(() =>
            {
                lpLoading.DisplayType = displayType;
                lpLoading.Visibility = System.Windows.Visibility.Visible;
                lpLoading.DisplayText = string.Format("{0}", message);
                
            }));
        }




        #region Event Handlers 

        /// <summary>
        /// Handles the Click event of the btnRemove control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
        private void btnRemove_Click(object sender, RoutedEventArgs e)
        {

            listBox1.SelectedItems.Cast<string>().ToList().ForEach(item => listBox1.Items.Remove(item));

            if (listBox1.Items.Count == 0)
            {
                btnProcessFiles.IsEnabled = false;
            }

        }
        /// <summary>
        /// Handles the Click event of the Button control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            bool canContinue = (this.cbCsv.IsChecked == false) ? ((this.cbBlg.IsChecked == false) ? false : true) : true;

            if (!canContinue)
            {
                DisplayMessageFromBGThread("Please select a file extension.", LoadingPanelDisplayType.OK);
            }
            else
            {
                Microsoft.Win32.OpenFileDialog dialog = new Microsoft.Win32.OpenFileDialog();

                if (this.cbCsv.IsChecked == true && this.cbBlg.IsChecked == true)
                {
                    dialog.Filter = "Windows Performance Log Types|*blg;*csv";
                }
                else if(this.cbBlg.IsChecked == true)
                {
                    dialog.Filter = "Windows Binary Performance Log File (*.blg)|*.blg";
                }
               
                else if(cbCsv.IsChecked ==true)
                {
                    dialog.Filter = "Comma Seperated Value (*.csv)|*.csv";
                }

                dialog.Multiselect = true;


                Nullable<bool> result = dialog.ShowDialog();


                // Get the selected file name and display in a TextBox 
                if (result == true)
                {
                    dialog.FileNames.ToList().Where(item => !listBox1.Items.Contains(item)).ToList().ForEach(file =>
                    {
                        listBox1.Items.Add(file);
                        btnProcessFiles.IsEnabled = true;
                    });

                }
            }
        }
        /// <summary>
        /// Handles the Click event of the btnBrowse control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
        private void btnBrowse_Click(object sender, RoutedEventArgs e)
        {
            FolderBrowserDialog dialog = new FolderBrowserDialog();
            dialog.RootFolder = Environment.SpecialFolder.MyComputer;

            DialogResult result = dialog.ShowDialog();

            if (result == System.Windows.Forms.DialogResult.OK)
            {
                txtWorkingDir.Text = dialog.SelectedPath;
            }
        }

        /// <summary>
        /// Handles the Click event of the btnProcessFiles control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>
        private void btnProcessFiles_Click(object sender, RoutedEventArgs e)
        {
           
            this._finalFile = string.Format(@"{1}\{0}.csv", txtOutputName.Text, txtWorkingDir.Text);

            DetermineApplicationFlow();
 
        }

        /// <summary>
        /// Handles the OnYesClick event of the lpLoading control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void lpLoading_OnYesClick(object sender, EventArgs e)
        {
           if(this._currentAppFlow == ApplicationStep.CheckForFile)
           {
               System.IO.File.Move(this._finalFile, this._finalFile.Replace(".csv", string.Format("_{0}.csv", DateTime.Now.ToString("MM_dd_yy_HH_mm_ss"))));
               this._currentAppFlow = ApplicationStep.ExecuteRelog;
               DetermineApplicationFlow();
           }
        }

        /// <summary>
        /// Handles the OnOKClick event of the lpLoading control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void lpLoading_OnOKClick(object sender, EventArgs e)
        {
            if(this._currentAppFlow == ApplicationStep.ProcessRelogResults)
            {
                this._currentAppFlow = ApplicationStep.CheckForFile;
            }

            this.lpLoading.Visibility = System.Windows.Visibility.Hidden;
        }

        /// <summary>
        /// Handles the OnNoClick event of the lpLoading control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void lpLoading_OnNoClick(object sender, EventArgs e)
        {
            if(this._currentAppFlow == ApplicationStep.CheckForFile)
            {
                System.IO.File.Delete(string.Format(@"{0}", this._finalFile));
                this._currentAppFlow = ApplicationStep.ExecuteRelog;
                DetermineApplicationFlow();
            }
        }

        /// <summary>
        /// Handles the OnRelogComplete event of the _processFiles control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void _processFiles_OnRelogComplete(object sender, EventArgs e)
        {
            this._currentAppFlow = ApplicationStep.ProcessRelogResults;
            DetermineApplicationFlow();
        }
        #endregion



    }




}
